class Swim extends egret.DisplayObjectContainer {

	/****************************** 资源与loading配置 ***************************/

    static resUrl: string   = "resource/default.res.json";
    static resRoot: string  = "resource/";
    static resGroup: string = "game";
    static loading: any     = LoadingUI;


	public constructor() {
		super();
		this.addEventListener(egret.Event.ADDED_TO_STAGE, this.createUI, this);
	}

	private stageWidth: number;												//舞台宽度
	private stageHeight: number;											//舞台高度
	private pool: egret.Sprite;												//泳池容器
	private poolLen: number = 50;											//泳池总长（单位米）
	private poolBgLen: number = 5;											//单位泳池背景长度（单位米）
	private poolLoopStart: number;											//泳池循环起点Y坐标
	private poolLoopEnd: number;											//泳池循环终点Y坐标
	private poolLoopCount: number = 0;										//泳池循环统计
	private basisSpeed: number = 24;										//基础速度
	private minSpeed: number = 6;											//最小速度
	private maxSpeed: number = 40;											//最大速度
	private speedUpRatio: number = 0.4;										//加速<率>
	private speedDownRatio: number = 0.4;									//减速<率>
	private unSpeedUp: egret.Timer = new egret.Timer(1000, 0);				//减速定时器
	private ready: egret.MovieClip;											//准备动作剪影
	private swim: egret.MovieClip;											//游泳动作剪影
	private onLeftAction: boolean = false;									//控制左键状态
	private onRightAction: boolean = false;									//控制右键状态
	private gameTime: egret.TextField;										//游戏计时
	private gameTimer: egret.Timer = new egret.Timer(10, 0);				//游戏计时定时器
	private gameStartTime: number;											//游戏开始时间
	private gameTip: egret.TextField;										//游戏提示
	private gameTipTexts: Array<string> = ["3", "2", "1", "READY", "GO!"];	//游戏倒计时提示文本
	private userHeadImg: egret.Bitmap;
	

	/********************************* 设置用户头像 ***********************************/

	public setUserHead(url: string): void {
		let imageLoader: egret.ImageLoader = new egret.ImageLoader();

		imageLoader.addEventListener(egret.Event.COMPLETE, (event: egret.Event) => {
			this.userHeadImg.bitmapData = event.currentTarget.data;
			egret.Tween.get(this.userHeadImg).to({alpha: 1}, 500);
		}, this);

		imageLoader.load(url);
	}


	/********************************* 获取比赛时间 ***********************************/

	public getRecord(): string {
		return this.gameTime.text;
	}

	
	/********************************* 创建UI ***********************************/

	private createUI(): void {
		this.stageWidth = this.stage.stageWidth;
		this.stageHeight = this.stage.stageHeight;

		let userHeadCon						= new egret.Sprite();
		let userHeadShade					= new egret.Shape();
		let userHeadImg						= this.userHeadImg = new egret.Bitmap();
		let gameTimeCon: egret.Sprite		= new egret.Sprite();
		let gameTimeName: egret.TextField	= new egret.TextField();
		let gameTime: egret.TextField		= this.gameTime = new egret.TextField();
		let gameTip: egret.TextField		= this.gameTip = new egret.TextField();

		//创建泳池
		this.createPool();

		//创建人物
		this.createSwimmer();

		//添加容器
		this.addChild(userHeadCon);
		this.addChild(gameTimeCon);
		this.addChild(gameTip);
		userHeadCon.addChild(userHeadShade);
		userHeadCon.addChild(userHeadImg);
		gameTimeCon.addChild(gameTimeName);
		gameTimeCon.addChild(gameTime);

		//设置用户头像容器样式
		userHeadCon.x = 36;
		userHeadCon.y = 32;
		userHeadCon.graphics.beginFill(0xefefef);
		userHeadCon.graphics.drawCircle(70, 70, 70);
		userHeadCon.graphics.endFill();
		
		//设置用户头像遮罩层样式
		userHeadShade.graphics.beginFill(0x000000);
		userHeadShade.graphics.drawCircle(70, 70, 70);
		userHeadShade.graphics.endFill();

		//设置用户头像图片样式
		userHeadImg.width /= userHeadImg.height / 140;
		userHeadImg.height = 140;
		userHeadImg.mask = userHeadShade;
		userHeadImg.alpha = 0;

		//设置游戏时间容器样式
		gameTimeCon.y = 32;

		//设置游戏时间标题样式
		gameTimeName.text = "Time";
		gameTimeName.size = 24;
		gameTimeName.textColor = 0xffffff;
		gameTimeName.width = this.stageWidth;
		gameTimeName.textAlign = egret.HorizontalAlign.CENTER;

		//设置游戏时间样式
		gameTime.text = "00:00.00";
		gameTime.size = 52;
		gameTime.bold = true;
		gameTime.textColor = 0xffffff;
		gameTime.width = this.stageWidth;
		gameTime.textAlign = egret.HorizontalAlign.CENTER;
		gameTime.y = gameTimeName.height;

		//设置游戏提示信息样式
		gameTip.textColor = 0xfff434;
		gameTip.size = 120;
		gameTip.bold = true;
		gameTip.width = this.stageWidth;
		gameTip.textAlign = egret.HorizontalAlign.CENTER;
		gameTip.anchorOffsetX = gameTip.width / 2;
		gameTip.anchorOffsetY = gameTip.size / 2;
		gameTip.x = this.stageWidth / 2;
		gameTip.y = 360;

		//准备游戏
		setTimeout(() => {
			this.readyAndStart();
		}, 2000);
	}


	/********************************* 准备游戏 ***********************************/

	private readyAndStart(index?: number): void {
		!index ? index = 0 : "";
		this.setTip(this.gameTipTexts[index], null, () => {

			//游戏准备倒计时
			if (index + 1 < this.gameTipTexts.length) {
				index++;
				this.readyAndStart(index);
			} 

			//开始游戏
			else {
				//跳水动作
				egret.Tween.get(this.ready)
					.to({y: this.stageHeight, scaleY: 1}, 300).call(() => {
					//添加游泳动作
					this.addChildAt(this.swim, this.getChildIndex(this.ready));
					//移除准备动作
					this.removeChild(this.ready);
					//创建控制按钮
					this.createControl();
					//监听游泳动作，每次完成播放下一次声效
					this.swim.addEventListener(egret.Event.LOOP_COMPLETE, () => {
						// console.log("bgg");
					}, this);
					//计算泳池位移
					this.addEventListener(egret.Event.ENTER_FRAME, this.poolYCalc, this);
					//更新游戏时间
					this.addEventListener(egret.Event.ENTER_FRAME, this.gameTimeCount, this);
					//游泳减速
					this.unSpeedUp.addEventListener(egret.TimerEvent.TIMER, this.goSpeedDown, this);
					this.unSpeedUp.start();
					//记录当前时间
					this.gameStartTime = Date.now();
					//播放游泳动作
					this.swim.gotoAndPlay(1, -1);
				});
			}
		});
	}


	/********************************* 设置游戏提示信息 ***********************************/

	private setTip(text: string, showTime?: number, callback?: Function): void {
		showTime = showTime !== undefined && showTime !== null ? showTime : 880;

		//移除动画
		egret.Tween.removeTweens(this.gameTip);

		//初始化游戏提示
		this.gameTip.scaleX = 0;
		this.gameTip.scaleY = 0;
		this.gameTip.alpha = 0;
		this.gameTip.text = text;

		//开启游戏提示
		egret.Tween.get(this.gameTip).to({
			alpha: 1,
			scaleX: 1.3,
			scaleY: 1.3
		}, 50).to({
			scaleX: 1,
			scaleY: 1
		}, 30).call(() => {

			//关闭游戏提示
			if (showTime !== 0) {
				egret.Tween.get(this.gameTip).wait(showTime).to({
					alpha: 0,
					scaleX: 0,
					scaleY: 0
				}, 30).call(() => {
					this.gameTip.text = "";
					callback ? callback() : "";
				});
			} 
			
			//showTime 设置为0则不关闭游戏提示
			else {
				callback ? callback() : "";
			}
			
		});
	}


	/********************************* 创建泳池 ***********************************/

	private createPool(): void {
		let pool: egret.Sprite			= this.pool = new egret.Sprite();
		let poolTop: egret.Bitmap		= ResMgmt.createBitmapByName("top_bg_png");
		let poolBg: egret.Bitmap		= ResMgmt.createBitmapByName("background_png");
		let poolSideLine: egret.Bitmap	= ResMgmt.createBitmapByName("side_line_png");
		let poolCenTLine: egret.Bitmap	= ResMgmt.createBitmapByName("center_line_png");
		let poolCenMLine: egret.Bitmap	= ResMgmt.createBitmapByName("line_03_png");
		let poolCenBLine: egret.Bitmap	= ResMgmt.createBitmapByName("center_line_png");
		let poolUnitsHeight: number		= poolBg.height;

		//添加容器
		this.addChild(pool);
		pool.addChild(poolTop);
		pool.addChild(poolBg);
		pool.addChild(poolSideLine);
		pool.addChild(poolCenTLine);
		pool.addChild(poolCenMLine);
		pool.addChild(poolCenBLine);

		//设置终点池台样式
		poolTop.height /= poolTop.width / this.stageWidth;
		poolTop.width = this.stageWidth;
		
		//设置泳池背景样式
		poolBg.y = poolSideLine.y = poolTop.height;
		poolBg.width = this.stageWidth;
		poolBg.height = poolUnitsHeight * 4;
		poolBg.fillMode = egret.BitmapFillMode.REPEAT;
		
		//设置泳池边线样式
		poolSideLine.anchorOffsetX = poolSideLine.width / 2;
		poolSideLine.x = this.stageWidth / 2;
		poolSideLine.height = poolUnitsHeight * 4;
		poolSideLine.fillMode = egret.BitmapFillMode.REPEAT;
		
		//设置泳池中线(上)样式
		poolCenTLine.anchorOffsetX = poolCenTLine.width / 2;
		poolCenTLine.anchorOffsetY = poolCenTLine.height / 2;
		poolCenTLine.x = this.stageWidth / 2;
		poolCenTLine.y = poolUnitsHeight - poolCenTLine.height / 2 + poolTop.height;
		poolCenTLine.rotation = 180;
		
		//设置泳池中线(中)样式
		poolCenMLine.anchorOffsetX = poolCenMLine.width / 2;
		poolCenMLine.x = this.stageWidth / 2;
		poolCenMLine.y = poolUnitsHeight + poolTop.height;
		poolCenMLine.height = poolUnitsHeight * 2;
		poolCenMLine.fillMode = egret.BitmapFillMode.REPEAT;
		
		//设置泳池中线(下)样式
		poolCenBLine.anchorOffsetX = poolCenBLine.width / 2;
		poolCenBLine.x = this.stageWidth / 2;
		poolCenBLine.y = poolUnitsHeight * 3 + poolTop.height;
		
		//设置泳池容器样式
		pool.y = pool.height * -1 + this.stageHeight;
		// pool.cacheAsBitmap = true;

		//添加循环始点和终点
		this.poolLoopStart = -1 * poolCenMLine.y - poolUnitsHeight;
		this.poolLoopEnd = -1 * poolCenMLine.y;
	}


	/********************************* 创建人物 ***********************************/

	private createSwimmer(): void {
		let img			= RES.getRes("swim_png");
		let data		= RES.getRes("swim_json");
		let factory		= new egret.MovieClipDataFactory(data, img);
		let readyClip	= factory.generateMovieClipData("ready");
		let swimClip	= factory.generateMovieClipData("swim");
		let ready		= this.ready = new egret.MovieClip(readyClip);
		let swim		= this.swim = new egret.MovieClip(swimClip);

		//添加容器
		this.addChild(ready);

		//设置准备动作剪影样式
		ready.anchorOffsetX = ready.width / 2;
		ready.anchorOffsetY = ready.height;
		ready.x = this.stageWidth / 2;
		ready.y = this.stageHeight + ready.height;
		ready.scaleY = 0.75;

		//设置游泳动作剪影样式
		swim.anchorOffsetX = swim.width / 2;
		swim.anchorOffsetY = swim.height;
		swim.x = this.stageWidth / 2;
		swim.y = this.stageHeight;
		swim.frameRate = this.basisSpeed;
	}


	/********************************* 创建控制按钮 ***********************************/

	private createControl(): void {
		let control: egret.Sprite		= new egret.Sprite();
		let left: egret.Shape			= new egret.Shape();
		let leftMatrix: egret.Matrix	= new egret.Matrix();
		let right: egret.Shape			= new egret.Shape();
		let rightMatrix: egret.Matrix	= new egret.Matrix();
		let tip: egret.TextField		= new egret.TextField();

		//添加容器
		control.addChild(left);
		control.addChild(right);
		control.addChild(tip);
		this.addChild(control);

		//绘制左键按钮
		leftMatrix.createGradientBox(188, 150, 0, 10, 0);
		left.graphics.beginGradientFill(
			egret.GradientType.LINEAR, 
			[0xffffff, 0xffffff], [1, 0.1], [0, 255], leftMatrix
		);
		left.graphics.moveTo(78, 0);
		left.graphics.lineTo(0, 75);
		left.graphics.lineTo(78, 150);
		left.graphics.lineTo(78, 0);
		left.graphics.drawRect(78, 33, 120, 84);
		left.graphics.endFill();

		//绘制右键按钮
		rightMatrix.createGradientBox(188, 150, 0, 0, 0);
		right.graphics.beginGradientFill(
			egret.GradientType.LINEAR, 
			[0xffffff, 0xffffff], [0.2, 1], [0, 255], rightMatrix
		);
		right.graphics.drawRect(0, 33, 120, 84);
		right.graphics.moveTo(120, 0);
		right.graphics.lineTo(198, 75);
		right.graphics.lineTo(120, 150);
		right.graphics.lineTo(120, 0);
		right.graphics.endFill();

		//设置控制容器样式
		control.width = this.stageWidth - 120;
		control.anchorOffsetX = control.width / 2;
		control.anchorOffsetY = control.height;
		control.x = this.stageWidth / 2;
		control.y = this.stageHeight + control.height;
		control.alpha = 0;
		egret.Tween.get(control).to({alpha: 1, y: this.stageHeight}, 500);

		//设置左键按钮样式
		left.anchorOffsetX = left.width / 2;
		left.anchorOffsetY = left.height / 2;
		left.x = left.width / 2;

		//设置右键按钮样式
		right.anchorOffsetX = right.width / 2;
		right.anchorOffsetY = right.height / 2;
		right.x = right.parent.width - right.width / 2;

		//设置操作提示文本
		tip.text = "点击左右键，向前游动";
		tip.size = 28;
		tip.textColor = 0xffffff;
		tip.width = tip.parent.width;
		tip.textAlign = egret.HorizontalAlign.CENTER;
		tip.y = tip.parent.height / 2;

		//添加事件
		left.touchEnabled = true;
		right.touchEnabled = true;
		left.addEventListener(egret.TouchEvent.TOUCH_TAP, this.leftAction, this);
		left.addEventListener(egret.TouchEvent.TOUCH_BEGIN, this.controlDown, this);
		left.addEventListener(egret.TouchEvent.TOUCH_END, this.controlUp, this);
		left.addEventListener(egret.TouchEvent.TOUCH_RELEASE_OUTSIDE, this.controlUp, this);
		right.addEventListener(egret.TouchEvent.TOUCH_TAP, this.rightAction, this);
		right.addEventListener(egret.TouchEvent.TOUCH_BEGIN, this.controlDown, this);
		right.addEventListener(egret.TouchEvent.TOUCH_END, this.controlUp, this);
		right.addEventListener(egret.TouchEvent.TOUCH_RELEASE_OUTSIDE, this.controlUp, this);
	}


	/********************************* 控制按钮按下事件 ***********************************/

	private controlDown(event: egret.TouchEvent): void {
		event.$currentTarget.scaleX = 0.95;
		event.$currentTarget.scaleY = 0.95;
	}


	/********************************* 控制按钮弹回事件 ***********************************/

	private controlUp(event: egret.TouchEvent): void {
		event.$currentTarget.scaleX = 1;
		event.$currentTarget.scaleY = 1;
	}


	/********************************* 控制左键按钮点击事件 ***********************************/

	private leftAction(): void {
		if (this.swim.$hasAddToStage && this.pool.y < 0) {
			this.unSpeedUp.stop();
			this.onLeftAction = !this.onLeftAction;
			this.onLeftAction ? this.goSpeedUp() : this.onRightAction = false;
			this.unSpeedUp.start();
		}
	}


	/********************************* 控制右键按钮点击事件 ***********************************/

	private rightAction(): void {
		if (this.swim.$hasAddToStage && this.pool.y < 0) {
			this.unSpeedUp.stop();
			this.onRightAction = !this.onRightAction;
			this.onRightAction ? this.goSpeedUp() : this.onLeftAction = false;
			this.unSpeedUp.start();
		}
	}


	/********************************* 加速 ***********************************/

	private goSpeedUp(): void {
		this.swim.frameRate * (1 + this.speedUpRatio) < this.maxSpeed 
			? this.swim.frameRate *= 1 + this.speedUpRatio : this.swim.frameRate = this.maxSpeed;
	}


	/********************************* 减速 ***********************************/

	private goSpeedDown(): void {
		if (this.swim.frameRate * (1 - this.speedDownRatio) < this.minSpeed) {
			this.swim.frameRate = this.minSpeed;
			this.unSpeedUp.stop();
		} else {
			this.swim.frameRate *= 1 - this.speedDownRatio;
		}
	}


	/********************************* 泳池位移计算 ***********************************/

	private poolYCalc(): void {
		let turn = this.poolLen / this.poolBgLen;
		if (this.poolLoopCount < turn - 1) {
			if (this.pool.y >= this.poolLoopEnd) {
				this.pool.y += this.poolLoopStart - this.poolLoopEnd;
				this.poolLoopCount !== 0 ? this.poolLoopCount++ : this.poolLoopCount = 2;
				this.poolLoopCount === turn / 2 || this.poolLoopCount >= turn / 4 * 3
					? this.setTip("最后" + (turn - this.poolLoopCount) * this.poolBgLen + "米", 1000) : "";
			}
		} else if (this.pool.y >= 0) {
			this.removeEventListener(egret.Event.ENTER_FRAME, this.poolYCalc, this);
			this.removeEventListener(egret.Event.ENTER_FRAME, this.gameTimeCount, this);
			this.swim.stop();
			this.unSpeedUp.stop();
			this.setTip("WIN!", 0);
			setTimeout(() => {
				ScenesMgmt.self.changeScene(Rank);
			}, 2000);
			return;
		}
		this.pool.y + this.swim.frameRate / 2.5 < 0 
			? this.pool.y += this.swim.frameRate / 2.5 : this.pool.y = 0;
	}


	/********************************* 游戏时间计时 ***********************************/

	private gameTimeCount(): void {
		this.gameTime.text = Utils.formatTime("mm:ss.SS", Date.now() - this.gameStartTime);
	}
}